﻿namespace Codeplex.Unity.AutoRegister.Test.Config
{
    using System;
    using System.Linq;
    using Codeplex.Unity.AutoRegister.Config;
    using Microsoft.Practices.Unity;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class AnnotationRegistTypeTraitBuilderTest
    {
        [TestMethod]
        public void ArgumentNullExceptionTest()
        {
            AssertEx.Throws<ArgumentNullException>(() => AnnotationRegistTypeTraitBuilder.Build(null));
        }

        [TestMethod]
        public void ArgumentExceptionTest()
        {
            AnnotationRegistTypeTraitBuilder.Build(typeof(Base)).Count().Is(0);
        }

        [TestMethod]
        public void BuildDefaultBehaviorTest()
        {
            var traits = AnnotationRegistTypeTraitBuilder.Build(typeof(DefaultParameterTestTarget));
            traits.IsNotNull();
            traits.Count().Is(1);
            traits.First().Is(o => o.FromType == typeof(DefaultParameterTestTarget) && o.ToType == typeof(DefaultParameterTestTarget) && o.Name == null &&
                o.LifetimeManager == typeof(PerResolveLifetimeManager) && o.InjectionMembers.Length == 0 &&
                o.InjectionMemberProvider.Name == "EmptyInjectionMemberProvider");
        }

        [TestMethod]
        public void BuildBehaviorTest()
        {
            var trait = AnnotationRegistTypeTraitBuilder.Build(typeof(CustomParameterTestTarget));
            trait.IsNotNull();
            trait.Count().Is(1);
            trait.First().Is(o => o.FromType == typeof(Base) && o.ToType == typeof(CustomParameterTestTarget) && o.Name == "Base" &&
                o.LifetimeManager == typeof(SynchronizedLifetimeManager) && o.InjectionMembers.Length == 0 &&
                o.InjectionMemberProvider == typeof(DummyInjectionMemberProvider));
        }

        [TestMethod]
        public void BuildExtendAttributeBehaviorTest()
        {
            var traits = AnnotationRegistTypeTraitBuilder.Build(typeof(ExtendAttributeTestTarget));
            traits.IsNotNull();
            traits.Count().Is(1);
            traits.First().Is(o => o.InjectionMembers.Length == 1 && o.InjectionMembers[0] is InjectionProperty);
        }

        [TestMethod]
        public void MultiExportTest()
        {
            var traits = AnnotationRegistTypeTraitBuilder.Build(typeof(MultiExportTarget)).ToArray();
            traits.Length.Is(2);
            traits.Select(t => t.Name).OrderBy(s => s).Is("A", "B");
        }

        class Base { }

        [UnityExport]
        class DefaultParameterTestTarget : Base { }

        [UnityExport(
            Name = "Base", 
            FromType = typeof(Base), 
            LifetimeManager = typeof(SynchronizedLifetimeManager),
            InjectionMemberProvider = typeof(DummyInjectionMemberProvider))]
        class CustomParameterTestTarget : Base { }

        [ExtendUnityExport]
        class ExtendAttributeTestTarget : Base { }

        [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
        class ExtendUnityExportAttribute : UnityExportAttribute
        {
            public ExtendUnityExportAttribute()
            {
                this.InjectionMembers = new[]
                {
                    new InjectionProperty("Foo", "bar")
                };
            }
        }

        [UnityExport(Name = "A")]
        [UnityExport(Name = "B")]
        class MultiExportTarget
        {
        }

        class DummyInjectionMemberProvider : InjectionMemberProvider
        {
            public override System.Collections.Generic.IEnumerable<InjectionMember> GetInjectionMembers()
            {
                throw new NotImplementedException();
            }
        }

    }
}
